#ifndef _IO_X86_H
#define _IO_X86_H

#include "types_x86.h"

/*********************************************************************************************************
  x86 处理器 MMIO 读
*********************************************************************************************************/

static inline u8 read8(addr_t addr)
{
    u8 val = *(volatile u8 *)addr;
    return val;
}

static inline u16 read16(addr_t addr)
{
    u16 val = *(volatile u16 *)addr;
    return val;
}

static inline u32 read32(addr_t addr)
{
    u32 val = *(volatile u32 *)addr;
    return val;
}

static inline u64 read64(addr_t addr)
{
    u64 val = *(volatile u64 *)addr;
    return val;
}

/*********************************************************************************************************
  x86 处理器 MMIO 写
*********************************************************************************************************/

static inline void write8(u8 val, addr_t addr)
{
    *(volatile u8 *)addr = val;
}

static inline void write16(u16 val, addr_t addr)
{
    *(volatile u16 *)addr = val;
}

static inline void write32(u32 val, addr_t addr)
{
    *(volatile u32 *)addr = val;
}

static inline void write64(u64 val, addr_t addr)
{
    *(volatile u64 *)addr = val;
}

/*********************************************************************************************************
  x86 处理器 I/O 端口读
*********************************************************************************************************/
static inline u8 inb(u16 port)
{
  u8 data;

  asm volatile("in %1,%0" : "=a" (data) : "d" (port));
  return data;
}

static inline void insl(int port, void *addr, int cnt)
{
  asm volatile("cld; rep insl" :
               "=D" (addr), "=c" (cnt) :
               "d" (port), "0" (addr), "1" (cnt) :
               "memory", "cc");
}

/*********************************************************************************************************
  x86 处理器 I/O 端口写
*********************************************************************************************************/
static inline void outb(u16 port, u8 data)
{
  asm volatile("out %0,%1" : : "a" (data), "d" (port));
}

static inline void outw(u16 port, u8 data)
{
  asm volatile("out %0,%1" : : "a" (data), "d" (port));
}

static inline void outsl(int port, void *addr, int cnt)
{
  asm volatile("cld; rep outsl" :
               "=S" (addr), "=c" (cnt) :
               "d" (port), "0" (addr), "1" (cnt) :
               "cc");
}

/*********************************************************************************************************
  x86 处理器内存写（memset）
*********************************************************************************************************/
static inline void stosb(void *addr, int data, int cnt)
{
  asm volatile("cld; rep stosb" :
               "=D" (addr), "=c" (cnt) :
               "0" (addr), "1" (cnt), "a" (data) :
               "memory", "cc");
}

static inline void stosl(void *addr, int data, int cnt)
{
  asm volatile("cld; rep stosl" :
               "=D" (addr), "=c" (cnt) :
               "0" (addr), "1" (cnt), "a" (data) :
               "memory", "cc");
}

#endif /* _IO_X86_H */